home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 051-060 / amok58 / audiosupport1.1 / audiosupport.mod < prev    next >
Text File  |  1993-11-04  |  9KB  |  309 lines

  1. (*-------------------------------------------------------------------------
  2.   :Program.       AudioSupport.mod
  3.   :Contents.      Easy sound programming
  4.   :Author.        Christian Stiens
  5.   :Address.       Heustiege 2, W-4710 Lüdinghausen
  6.   :Copyright.     PD
  7.   :Language.      Oberon
  8.   :Translator.    Amiga Oberon V2.01 [fbs]
  9.   :History.       V1.0, 25-Aug-90: First release
  10.   :History.       V1.1, 24-Jul-91: Oberon, +PlayLoopSound
  11.   :History.                        +DontAbort, +SetPriority
  12. -------------------------------------------------------------------------*)
  13.  
  14.  
  15. (*---------------------------- DEFINITION --------------------------------
  16.  
  17. DEFINITION AudioSupport;
  18.  
  19. CONST
  20.   clock = 3563220;   (* per = clock / freq *)
  21.   left0 = 0;
  22.   right0 = 1;
  23.   right1 = 2;
  24.   left1 = 3;
  25.  
  26. PROCEDURE SetPriority(pri: SHORTINT);
  27.  
  28.   (* OpenChannel will open channels with priority pri *)
  29.  
  30. PROCEDURE DontAbort;
  31.  
  32.   (* Program will not be aborted if channels are not free *)
  33.  
  34. PROCEDURE OpenChannel(mask: SET): SHORTINT;
  35.  
  36.   (* Open one channel of mask and return its channel number *)
  37.  
  38. PROCEDURE CloseChannel(chan: SHORTINT);
  39.  
  40.   (* Close the channel chan (which not has to be open). All open
  41.      channels are closed automatic at program end *)
  42.  
  43. PROCEDURE PlaySound(chan: SHORTINT; sound: e.ADDRESS; size: LONGINT;
  44.                     per, vol, cyc: INTEGER);
  45.  
  46.   (* Play the sample at address 'sound' (in chip mem) with period 'per'
  47.      (per >= 124), volume 'vol' (0 <= vol <= 64) 'cyc' times (cyc=0 means
  48.      forever) *)
  49.  
  50. PROCEDURE PlayLoopSound(chan: SHORTINT; sound: e.ADDRESS;
  51.                         oneShot, repeat: LONGINT;
  52.                         per, vol: INTEGER);
  53.  
  54.   (* Play a looped sound with attack length 'oneShot' and looped
  55.      length 'repeat' *)
  56.  
  57. PROCEDURE StopSound(chan: SHORTINT);
  58.  
  59.   (* Stop the sound in channel 'chan' *)
  60.  
  61. PROCEDURE CheckSound(chan: SHORTINT): BOOLEAN;
  62.  
  63.   (* Returns 'TRUE' if channel 'chan' is playing at this moment *)
  64.  
  65. PROCEDURE ModifySound(chan: SHORTINT; per, vol: INTEGER);
  66.  
  67.   (* Modifies frequency and volume of a running sound *)
  68.  
  69. PROCEDURE WaitSound(chan: SHORTINT);
  70.  
  71.   (* Waits until channel 'chan' has finished his sound *)
  72.  
  73. PROCEDURE Filter(on: BOOLEAN);
  74.  
  75.   (* Set the Hardware filter on or off *)
  76.  
  77. ----------------------------- END DEFINITION ---------------------------*)
  78.  
  79.  
  80.  
  81. MODULE AudioSupport;
  82.  
  83.   (* $StackChk- $NilChk- $RangeChk- $OvflChk- $ReturnChk- $CaseChk- *)
  84.  
  85.   IMPORT
  86.     au : Audio,
  87.     e  : Exec,
  88.     es : ExecSupport,
  89.     hw : Hardware,
  90.     rq : Requests,
  91.     sys: SYSTEM;
  92.  
  93.   CONST
  94.     clock  * = 3563220;
  95.  
  96.     left0  * = 0;
  97.     right0 * = 1;
  98.     right1 * = 2;
  99.     left1  * = 3;
  100.  
  101.     cantOpen = "Can't open audio channel";
  102.     notOpen  = "Audio channel not open";
  103.     illegal  = "Illegal audio channel";
  104.  
  105.   VAR
  106.     mp1            : ARRAY 4 OF e.MsgPortPtr;
  107.     ioa1,ioa2,ioa3 : ARRAY 4 OF au.IOAudioPtr;
  108.     open           : ARRAY 4 OF BOOLEAN;
  109.     looped         : ARRAY 4 OF BOOLEAN;
  110.     lastPer,lastVol: ARRAY 4 OF INTEGER;
  111.     priority       : SHORTINT;
  112.     abort          : BOOLEAN;
  113.  
  114.  
  115.   PROCEDURE SetPriority*(pri: SHORTINT);
  116.   BEGIN
  117.     priority := pri
  118.   END SetPriority;
  119.  
  120.   PROCEDURE DontAbort*;
  121.   BEGIN
  122.     abort := FALSE;
  123.   END DontAbort;
  124.  
  125.   PROCEDURE OpenChannel*(mask: SET): SHORTINT;
  126.     VAR
  127.       allocMask : ARRAY 4 OF SHORTSET;
  128.       chan      : SHORTINT;
  129.       i         : INTEGER;
  130.       mp        : e.MsgPortPtr;
  131.       ioa       : POINTER TO ARRAY 3 OF au.IOAudio;
  132.   BEGIN
  133.     IF mask * {0..3} = {} THEN mask := {0..3} END;
  134.     mp := es.CreatePort("",0);
  135.     IF mp # NIL THEN
  136.       ioa := e.AllocMem(sys.SIZE(ioa^),LONGSET{e.memClear,e.public});
  137.       IF ioa # NIL THEN
  138.         ioa[0].request.message.node.type := e.message;
  139.         ioa[0].request.message.length := sys.SIZE(au.IOAudio);
  140.         ioa[0].request.message.replyPort := mp;
  141.         i := 0;
  142.         chan := 0; WHILE chan < 4 DO
  143.           IF chan IN mask THEN allocMask[i] := SHORTSET{chan}; INC(i) END;
  144.           INC(chan)
  145.         END;
  146.         ioa[0].request.message.node.pri := priority;
  147.         ioa[0].data   := sys.ADR(allocMask);
  148.         ioa[0].length := i;
  149.         IF e.OpenDevice(au.audioName,0,sys.VAL(e.MessagePtr,ioa),LONGSET{})
  150.                                                                      = 0 THEN
  151.           ioa^[1] := ioa^[0];
  152.           ioa^[2] := ioa^[0];
  153.           CASE sys.VAL(LONGINT,ioa[0].request.unit) OF
  154.             1: chan := left0  |
  155.             2: chan := right0 |
  156.             4: chan := right1 |
  157.             8: chan := left1
  158.           ELSE
  159.             HALT(20);
  160.           END;
  161.           mp1[chan] := mp;
  162.           ioa1[chan] := sys.ADR(ioa[0]);
  163.           ioa2[chan] := sys.ADR(ioa[1]);
  164.           ioa3[chan] := sys.ADR(ioa[2]);
  165.           ioa1[chan].data := 0;
  166.           open[chan] := TRUE;
  167.           looped[chan] := FALSE;
  168.           RETURN chan
  169.         END;
  170.         e.FreeMem(ioa,sys.SIZE(ioa^));
  171.       END;
  172.       es.DeletePort(mp)
  173.     END;
  174.     rq.Assert(~abort,cantOpen);
  175.     RETURN -1
  176.   END OpenChannel;
  177.  
  178.   PROCEDURE CloseChannel*(chan: SHORTINT);
  179.   BEGIN
  180.     IF (chan >= 0) & (chan <= 3) & open[chan] THEN
  181.       e.CloseDevice(ioa1[chan]);
  182.       e.FreeMem(ioa1[chan],3*sys.SIZE(au.IOAudio));
  183.       es.DeletePort(mp1[chan]);
  184.       open[chan] := FALSE;
  185.     END
  186.   END CloseChannel;
  187.  
  188.   PROCEDURE CheckChannel(chan: SHORTINT): BOOLEAN;
  189.   BEGIN
  190.     CASE chan OF
  191.        -1 : rq.Assert(~abort,notOpen); RETURN FALSE |
  192.      0..3 : IF open[chan] THEN RETURN TRUE
  193.             ELSE rq.Assert(~abort,notOpen); RETURN FALSE END
  194.     ELSE    rq.Assert(FALSE,illegal);
  195.     END;
  196.   END CheckChannel;
  197.  
  198.   PROCEDURE PlaySound*(chan:SHORTINT; sound:e.ADDRESS; size:LONGINT;
  199.                        per,vol,cyc:INTEGER);
  200.   BEGIN
  201.     IF ~CheckChannel(chan) THEN RETURN END;
  202.     IF looped[chan] THEN es.AbortIO(ioa2[chan]) END;
  203.     es.AbortIO(ioa1[chan]);
  204.     IF size > 1 THEN
  205.       ioa1[chan].request.command := e.write;
  206.       ioa1[chan].request.flags := SHORTSET{au.pervol};
  207.       ioa1[chan].data   := sound;
  208.       ioa1[chan].length := size;
  209.       ioa1[chan].period := per;
  210.       ioa1[chan].volume := vol;
  211.       ioa1[chan].cycles := cyc;
  212.       es.BeginIO(ioa1[chan]);
  213.     END;
  214.     lastPer[chan] := per;
  215.     lastVol[chan] := vol;
  216.     looped[chan] := FALSE;
  217.   END PlaySound;
  218.  
  219.   PROCEDURE PlayLoopSound*(chan:SHORTINT; sound:e.ADDRESS;
  220.                            oneShot,repeat:LONGINT;
  221.                            per,vol:INTEGER);
  222.   BEGIN
  223.     IF oneShot = 0 THEN
  224.       PlaySound(chan,sound,repeat,per,vol,0);
  225.       RETURN;
  226.     END;
  227.     IF repeat = 0 THEN
  228.       PlaySound(chan,sound,oneShot,per,vol,1);
  229.       RETURN;
  230.     END;
  231.     IF ~CheckChannel(chan) THEN RETURN END;
  232.     es.AbortIO(ioa2[chan]);
  233.     es.AbortIO(ioa1[chan]);
  234.     ioa1[chan].request.command := e.write;
  235.     ioa1[chan].request.flags := SHORTSET{au.pervol};
  236.     ioa1[chan].data := sound;
  237.     ioa1[chan].length := oneShot;
  238.     ioa1[chan].period := per;
  239.     ioa1[chan].volume := vol;
  240.     ioa1[chan].cycles := 1;
  241.     es.BeginIO(ioa1[chan]);
  242.     ioa2[chan].request.command := e.write;
  243.     ioa2[chan].request.flags := SHORTSET{};
  244.     ioa2[chan].data := sound+oneShot;
  245.     ioa2[chan].length := repeat;
  246.     ioa2[chan].cycles := 0;
  247.     es.BeginIO(ioa2[chan]);
  248.     lastPer[chan] := per;
  249.     lastVol[chan] := vol;
  250.     looped[chan] := TRUE;
  251.   END PlayLoopSound;
  252.  
  253.   PROCEDURE StopSound*(chan: SHORTINT);
  254.   BEGIN
  255.     IF ~CheckChannel(chan) THEN RETURN END;
  256.     IF looped[chan] THEN
  257.       es.AbortIO(ioa2[chan]); looped[chan] := FALSE
  258.     END;
  259.     es.AbortIO(ioa1[chan])
  260.   END StopSound;
  261.  
  262.   PROCEDURE CheckSound*(chan: SHORTINT): BOOLEAN;
  263.   BEGIN
  264.     IF ~CheckChannel(chan) THEN RETURN FALSE END;
  265.     RETURN looped[chan] OR ((ioa1[chan].data # 0) & ~e.CheckIO(ioa1[chan]))
  266.   END CheckSound;
  267.  
  268.   PROCEDURE ModifySound*(chan:SHORTINT; per,vol: INTEGER);
  269.   BEGIN
  270.     IF ~CheckChannel(chan) THEN RETURN END;
  271.     IF (vol#lastVol[chan]) OR (per#lastPer[chan]) THEN
  272.       ioa3[chan].request.command := au.perVol;
  273.       ioa3[chan].period := per;
  274.       ioa3[chan].volume := vol;
  275.       e.OldDoIO(ioa3[chan]);
  276.       lastPer[chan] := per;
  277.       lastVol[chan] := vol;
  278.     END;
  279.   END ModifySound;
  280.  
  281.   PROCEDURE WaitSound*(chan: SHORTINT);
  282.   BEGIN
  283.     IF ~CheckChannel(chan) THEN RETURN END;
  284.     IF NOT looped[chan] THEN e.OldWaitIO(ioa1[chan]) END;
  285.   END WaitSound;
  286.  
  287.   PROCEDURE Filter*(on: BOOLEAN);
  288.   BEGIN
  289.     IF on THEN
  290.       EXCL(hw.ciaa.pra,hw.led)
  291.     ELSE
  292.       INCL(hw.ciaa.pra,hw.led)
  293.     END
  294.   END Filter;
  295.  
  296. BEGIN
  297.   priority     := 0;
  298.   abort        := TRUE;
  299.   open[left0]  := FALSE;
  300.   open[right0] := FALSE;
  301.   open[right1] := FALSE;
  302.   open[left1]  := FALSE;
  303. CLOSE
  304.   CloseChannel(left0);
  305.   CloseChannel(right0);
  306.   CloseChannel(right1);
  307.   CloseChannel(left1);
  308. END AudioSupport.
  309.